home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2008 April / PCgo 2008-04 (DVD).iso / interface / contents / demoversionen_3846 / 13664 / files / Data1.cab / autorect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-22  |  27.3 KB  |  1,036 lines

  1. /******************************************************************/
  2. /*                                                                */
  3. /*                      TurboCAD for Windows                      */
  4. /*                   Copyright (c) 1993 - 2001                    */
  5. /*             International Microcomputer Software, Inc.         */
  6. /*                            (IMSI)                              */
  7. /*                      All rights reserved.                      */
  8. /*                                                                */
  9. /******************************************************************/
  10.  
  11. // AutoRect.cpp : implementation file
  12. //
  13.  
  14. #include "stdafx.h"
  15. #include "RRect.h"
  16. #include "AutoRect.h"  // This class
  17. #include "RectPage.h"  // Property page class
  18. #include "Imsigx.h"   // TurboCAD interfaces
  19. #include <math.h>
  20.  
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. // Standard variants
  28. COleVariant t(-1L, VT_BOOL);
  29. COleVariant f(0L, VT_BOOL);
  30. COleVariant z(0.0);
  31. COleVariant missing((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
  32. const double PI = 3.14159265;
  33.  
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CAutoRect
  36.  
  37. const IID IID_IGraphic = 
  38.     {0x6A481109,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  39.  
  40. IMPLEMENT_DYNCREATE(CAutoRect, CCmdTarget)
  41.  
  42. CAutoRect::CAutoRect() :
  43.     m_pRectPage(NULL)
  44. {
  45.     EnableAutomation();
  46.  
  47.     // To keep the application running as long as an OLE automation 
  48.     //    object is active, the constructor calls AfxOleLockApp.
  49.     
  50.     AfxOleLockApp();
  51. }
  52.  
  53. CAutoRect::~CAutoRect()
  54. {
  55.     // To terminate the application when all objects created with
  56.     //     with OLE automation, the destructor calls AfxOleUnlockApp.
  57.     
  58.     AfxOleUnlockApp();
  59. }
  60.  
  61.  
  62. void CAutoRect::OnFinalRelease()
  63. {
  64.     // When the last reference for an automation object is released
  65.     // OnFinalRelease is called.  The base class will automatically
  66.     // deletes the object.  Add additional cleanup required for your
  67.     // object before calling the base class.
  68.  
  69.     CCmdTarget::OnFinalRelease();
  70. }
  71.  
  72.  
  73. BEGIN_MESSAGE_MAP(CAutoRect, CCmdTarget)
  74.     //{{AFX_MSG_MAP(CAutoRect)
  75.         // NOTE - the ClassWizard will add and remove mapping macros here.
  76.     //}}AFX_MSG_MAP
  77. END_MESSAGE_MAP()
  78.  
  79. BEGIN_DISPATCH_MAP(CAutoRect, CCmdTarget)
  80.     //{{AFX_DISPATCH_MAP(CAutoRect)
  81.     DISP_PROPERTY_EX(CAutoRect, "ClassID", GetClassID, SetNotSupported, VT_BSTR)
  82.     DISP_PROPERTY_EX(CAutoRect, "Description", GetDescription, SetNotSupported, VT_BSTR)
  83.     DISP_FUNCTION(CAutoRect, "GetPropertyInfo", GetPropertyInfo, VT_I4, VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT)
  84.     DISP_FUNCTION(CAutoRect, "GetPageInfo", GetPageInfo, VT_I4, VTS_DISPATCH VTS_PI4 VTS_PVARIANT)
  85.     DISP_FUNCTION(CAutoRect, "GetWizardInfo", GetWizardInfo, VT_I4, VTS_PVARIANT)
  86.     DISP_FUNCTION(CAutoRect, "GetEnumNames", GetEnumNames, VT_I4, VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  87.     DISP_FUNCTION(CAutoRect, "PageControls", PageControls, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_I4 VTS_BOOL)
  88.     DISP_FUNCTION(CAutoRect, "PageDone", PageDone, VT_EMPTY, VTS_DISPATCH VTS_PVARIANT)
  89.     DISP_FUNCTION(CAutoRect, "PropertyPages", PropertyPages, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  90.     DISP_FUNCTION(CAutoRect, "Wizard", Wizard, VT_BOOL, VTS_DISPATCH VTS_PVARIANT)
  91.     DISP_FUNCTION(CAutoRect, "OnGeometryChanged", OnGeometryChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  92.     DISP_FUNCTION(CAutoRect, "OnGeometryChanging", OnGeometryChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  93.     DISP_FUNCTION(CAutoRect, "OnNewGraphic", OnNewGraphic, VT_BOOL, VTS_DISPATCH VTS_BOOL)
  94.     DISP_FUNCTION(CAutoRect, "OnCopyGraphic", OnCopyGraphic, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_VARIANT)
  95.     DISP_FUNCTION(CAutoRect, "OnPropertyChanged", OnPropertyChanged, VT_EMPTY, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  96.     DISP_FUNCTION(CAutoRect, "OnPropertyChanging", OnPropertyChanging, VT_BOOL, VTS_DISPATCH VTS_I4 VTS_PVARIANT VTS_PVARIANT)
  97.     DISP_FUNCTION(CAutoRect, "OnPropertyGet", OnPropertyGet, VT_EMPTY, VTS_DISPATCH VTS_I4)
  98.     DISP_FUNCTION(CAutoRect, "Draw", Draw, VT_BOOL, VTS_DISPATCH VTS_DISPATCH VTS_PVARIANT)
  99.     DISP_FUNCTION(CAutoRect, "Regen", Regen, VT_EMPTY, VTS_DISPATCH)
  100.     DISP_FUNCTION(CAutoRect, "Initialize", Initialize, VT_BOOL, VTS_DISPATCH)
  101.     //}}AFX_DISPATCH_MAP
  102. END_DISPATCH_MAP()
  103.  
  104. // Note: we add support for IID_ISmartObjectServer to support typesafe binding
  105. //  from VBA.  This IID must match the GUID that is attached to the 
  106. //  dispinterface in the .ODL file.
  107.  
  108. static const IID IID_ISmartObjectServer =
  109. {0x6A481303,0xE531,0x11CF,{0xA1,0x15,0x00,0xA0,0x24,0x15,0x8D,0xAF}};
  110.  
  111. BEGIN_INTERFACE_MAP(CAutoRect, CCmdTarget)
  112.     INTERFACE_PART(CAutoRect, IID_ISmartObjectServer, Dispatch)
  113. END_INTERFACE_MAP()
  114.  
  115. IMPLEMENT_OLECREATE(CAutoRect, "RRect.Rectangle", 0x7724bb36, 0xb671, 0x11d0, 0x9b, 0x3b, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);//# Non-localizable string#
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118. // CAutoRect message handlers
  119.  
  120. BSTR CAutoRect::GetClassID() 
  121. {
  122.     // Convert our GUID (see IMPLEMENT_OLECREATE macro) to a string
  123.     LPOLESTR olestr;
  124.     HRESULT hRes = ::StringFromCLSID(guid, &olestr);
  125.     if (FAILED(hRes))
  126.         return NULL;
  127.  
  128.     BSTR bstr = ::SysAllocString(olestr);
  129.     CoTaskMemFree(olestr);
  130.     return bstr;
  131. }
  132.  
  133. BSTR CAutoRect::GetDescription() 
  134. {
  135.     // Get the description from the resource
  136.     CString strResult;
  137.     strResult.LoadString(IDS_AUTORECT_DESCRIPTION);
  138.  
  139.     return strResult.AllocSysString();
  140. }
  141.  
  142. const long VT_INTEGER_ENUM = VT_I2 + 100;
  143. const long VT_LONG_ENUM = VT_I4 + 100;
  144. const long VT_STRING_ENUM = VT_BSTR + 100;
  145.  
  146. const long GF_COSMETIC = 128;
  147.  
  148. enum StockPages {
  149.     PP_STOCK_PEN = 1,
  150.     PP_STOCK_BRUSH = 2,
  151.     PP_STOCK_TEXT = 4,
  152.     PP_STOCK_INSERT = 8,
  153.     PP_STOCK_VIEWPORT = 16,
  154.     PP_STOCK_AUTO = 32
  155. };
  156.  
  157. // our Rounded rectangle object has only one property called Roundess
  158. const long nProperties = 1;
  159. // define one property
  160. enum PropertyIDs 
  161. {
  162.    idRoundness = 1,
  163. };
  164.  
  165. long CAutoRect::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults) 
  166. {
  167.      ASSERT(Names->vt == (VT_ARRAY|VT_BSTR));
  168.     ASSERT(Types->vt == (VT_ARRAY|VT_I4));
  169.     ASSERT(IDs->vt == (VT_ARRAY|VT_I4));
  170.     ASSERT(Defaults->vt == (VT_ARRAY|VT_VARIANT));
  171.  
  172.      SAFEARRAYBOUND bound = { nProperties, 0 };
  173.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  174.         return 0;
  175.     if (FAILED(::SafeArrayRedim(Types->parray, &bound)))
  176.         return 0;
  177.     if (FAILED(::SafeArrayRedim(IDs->parray, &bound)))
  178.         return 0;
  179.     if (FAILED(::SafeArrayRedim(Defaults->parray, &bound)))
  180.         return 0;
  181.  
  182.     BSTR* rgNames;
  183.     long* rgTypes;
  184.     long* rgIDs;
  185.     VARIANT* rgDefaults; 
  186.     long lReturn = 0;
  187.     if (SUCCEEDED(::SafeArrayAccessData(Names->parray, (void**)&rgNames)))
  188.     {
  189.         if (SUCCEEDED(::SafeArrayAccessData(Types->parray, (void**)&rgTypes)))
  190.         {
  191.             if (SUCCEEDED(::SafeArrayAccessData(IDs->parray, (void**)&rgIDs)))
  192.             {
  193.                 if (SUCCEEDED(::SafeArrayAccessData(Defaults->parray, (void**)&rgDefaults)))
  194.                 {
  195.                     CString strStr;
  196.                     strStr.LoadString(IDS_PROPERTYROUNDESS);
  197.                     //rgNames[0] = ::SysAllocString(OLESTR("Roundness"));//# Localizable string#
  198.                     rgNames[0] = ::SysAllocString(strStr.AllocSysString());
  199.                     rgTypes[0] = VT_R8;
  200.                     rgIDs[0] = idRoundness;
  201.                     rgDefaults[0].vt = VT_R8;
  202.                     rgDefaults[0].dblVal = 50.0;
  203.  
  204.                     ::SafeArrayUnaccessData(Defaults->parray);
  205.                     lReturn = nProperties;
  206.                 }
  207.                 ::SafeArrayUnaccessData(IDs->parray);
  208.             }
  209.             ::SafeArrayUnaccessData(Types->parray);
  210.         }
  211.         ::SafeArrayUnaccessData(Names->parray);
  212.     }
  213.     return lReturn;
  214. }
  215.  
  216. long CAutoRect::GetPageInfo(LPDISPATCH /*AGraphic*/, long* StockPages, VARIANT FAR* Names) 
  217. {
  218.     ASSERT(StockPages != NULL);
  219.      ASSERT(Names->vt == VT_ARRAY|VT_BSTR);
  220.  
  221.     // Request pen page and auto page
  222.     *StockPages = PP_STOCK_PEN | PP_STOCK_AUTO;
  223.  
  224.      SAFEARRAYBOUND bound = { 1, 0 };
  225.     if (FAILED(::SafeArrayRedim(Names->parray, &bound)))
  226.         return 0;
  227.  
  228.     CString strCaption;
  229.     strCaption.LoadString(IDS_AUTORECT_CAPTION);
  230.     BSTR bstrCaption = strCaption.AllocSysString();
  231.  
  232.     long lIndex = 0;
  233.     if (FAILED(SafeArrayPutElement(Names->parray, &lIndex, (void*)bstrCaption)))
  234.     {
  235.         ::SysFreeString(bstrCaption);
  236.         return 0;
  237.     }
  238.     return 1;
  239. }
  240.  
  241. long CAutoRect::GetWizardInfo(VARIANT FAR* Names) 
  242. {
  243.     // No wizards, nothing to do
  244.     return 0;
  245. }
  246.  
  247. long CAutoRect::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values) 
  248. {
  249.     // Should never be called!
  250.     return 0;
  251. }
  252.  
  253. double GetRoundness(IGraphic* pIGraphic)
  254. {
  255.     double roundness = 50.0;
  256.     Properties* pProps = NULL;
  257.     Property* pProp;
  258.     COleVariant varIndex, varValue;
  259.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  260.     {
  261.         CString strStr;
  262.         strStr.LoadString(IDS_PROPERTYROUNDESS);
  263.         varIndex = LPCTSTR(strStr);
  264.         if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  265.         {
  266.             if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  267.                 varValue.vt == VT_R8)
  268.             {
  269.                 roundness = varValue.dblVal;
  270.             }
  271.             pProp->Release();
  272.         }
  273.         pProps->Release();
  274.     }
  275.     return roundness;
  276. }
  277.  
  278. void SetRoundness(IGraphic* pIGraphic, double roundness)
  279. {
  280.     Properties* pProps = NULL;
  281.     Property* pProp;
  282.     COleVariant varIndex;
  283.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  284.     {
  285.         CString strStr;
  286.         strStr.LoadString(IDS_PROPERTYROUNDESS);
  287.         varIndex = LPCTSTR(strStr);
  288.         if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  289.         {
  290.             COleVariant varValue;
  291.             varValue.vt = VT_R8;
  292.             varValue.dblVal = roundness;
  293.             pProp->put_Value(0, &varValue);
  294.             pProp->Release();
  295.         }
  296.         pProps->Release();
  297.     }
  298. }
  299.  
  300. BOOL CAutoRect::PageControls(LPDISPATCH ThisRegenMethod, LPDISPATCH AGraphic, long PageNumber, BOOL SaveProperties) 
  301. {
  302.     IGraphic* pIGraphic = NULL;
  303.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  304.         return FALSE;
  305.  
  306.     BOOL bReturn = FALSE;
  307.     Properties* pProps = NULL;
  308.     Property* pProp;
  309.     COleVariant varIndex, varValue;
  310.     if (SUCCEEDED(pIGraphic->get_Properties(&pProps)))
  311.     {
  312.         if (SaveProperties)
  313.         {
  314.             if (m_pRectPage != NULL)
  315.             {
  316.                 // Note: the following can fail (for non-rounded rect graphics)
  317.                 CString strStr;
  318.                 strStr.LoadString(IDS_PROPERTYROUNDESS);
  319.                 varIndex = LPCTSTR(strStr);
  320.                 if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  321.                 {
  322.                     varValue = (const long)m_pRectPage->m_roundness;
  323.                     pProp->put_Value(0, &varValue);
  324.                     pProp->Release();
  325.                     varValue.Clear();
  326.                 }
  327.                 bReturn = TRUE;
  328.             }
  329.         }
  330.         else
  331.         {
  332.             ASSERT(m_pRectPage == NULL);
  333.             m_pRectPage = new CRectPage();
  334.  
  335.             // Note: the following can fail (for indeterminate values)
  336.             CString strStr;
  337.             strStr.LoadString(IDS_PROPERTYROUNDESS);
  338.             varIndex = LPCTSTR(strStr);
  339.             if (SUCCEEDED(pProps->get_Item(&varIndex, &pProp)))
  340.             {
  341.                 if (SUCCEEDED(pProp->get_Value(0, &varValue)) &&
  342.                     varValue.vt == VT_R8)
  343.                     m_pRectPage->m_roundness = varValue.dblVal;
  344.                 pProp->Release();
  345.                 varValue.Clear();
  346.             }
  347.             bReturn = TRUE;
  348.         }
  349.         pProps->Release();
  350.     }
  351.  
  352.     pIGraphic->Release();
  353.     return bReturn;
  354. }
  355.  
  356. void CAutoRect::PageDone(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  357. {
  358.     // We're finished with the page
  359.     delete m_pRectPage;
  360.     m_pRectPage = NULL;
  361. }
  362.  
  363. BOOL CAutoRect::PropertyPages(LPDISPATCH ThisRegenMethod, VARIANT FAR* PageNumber) 
  364. {
  365.     if (m_pRectPage == NULL)
  366.         return FALSE;
  367.  
  368.     // Run the dialog and get the results
  369.     int nResult = m_pRectPage->DoModal();
  370.     return (nResult == IDOK);
  371. }
  372.  
  373. BOOL CAutoRect::Wizard(LPDISPATCH ThisRegenMethod, VARIANT FAR* WizardNumber) 
  374. {
  375.     // No wizards, so just return FALSE.
  376.     return FALSE;
  377. }
  378.  
  379. void CAutoRect::OnGeometryChanged(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  380. {
  381. }
  382.  
  383. BOOL CAutoRect::OnGeometryChanging(LPDISPATCH AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew) 
  384. {
  385.     // OK to change our geometry, so just return TRUE.
  386.     return TRUE;
  387. }
  388.  
  389. BOOL CAutoRect::OnNewGraphic(LPDISPATCH AGraphic, BOOL Copy) 
  390. {
  391.     // Return FALSE on failure.
  392.     // For copies, usually do nothing.
  393.     if (Copy)
  394.         return TRUE;
  395.  
  396.     // Add vertices, etc. for new graphic here.
  397.  
  398.     IGraphic* pIGraphic = NULL;
  399.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  400.         return FALSE;
  401.  
  402.     Vertices* pVerts;
  403.     IVertex* pIVertex;
  404.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  405.     {
  406.         COleVariant x;
  407.         COleVariant y;
  408.  
  409.         // First 2 vertices are lower left and upper right corners.
  410.         const double corners[2*2] = { -1.0, -0.5, 1.0, 0.5 };
  411.         for (int i = 0; i < 2*2; )
  412.         {
  413.             x = corners[i++];
  414.             y = corners[i++];
  415.  
  416.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  417.                 &f /*penDown*/, 
  418.                 &t /*selectable*/,
  419.                 &f /*snappable*/,
  420.                 &f /*editable*/, 
  421.                 &f /*linkable*/,
  422.                 &f /*calculated*/,
  423.                 &missing /*before*/,
  424.                 &missing /*after*/,
  425.                 &pIVertex)))
  426.                 pIVertex->Release();
  427.         }
  428.  
  429.         // Third vertex is rounding handle (calculated)
  430.         double r = 0.5 * GetRoundness(pIGraphic) / 100.0;
  431.         double offset = 0.1 * r;
  432.         x = 1.0 - r;
  433.         y = 0.5 + offset;
  434.         if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  435.             &f /*penDown*/, 
  436.             &f /*selectable*/,
  437.             &f /*snappable*/,
  438.             &f /*editable*/, 
  439.             &f /*linkable*/,
  440.             &f /*calculated*/,
  441.             &missing /*before*/,
  442.             &missing /*after*/,
  443.             &pIVertex)))
  444.             pIVertex->Release();
  445.  
  446.         // Fourth vertex is rounding handle (editable)
  447.         if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  448.             &f /*penDown*/, 
  449.             &t /*selectable*/,
  450.             &f /*snappable*/,
  451.             &t /*editable*/, 
  452.             &f /*linkable*/,
  453.             &f /*calculated*/,
  454.             &missing /*before*/,
  455.             &missing /*after*/,
  456.             &pIVertex)))
  457.             pIVertex->Release();
  458.  
  459.         pIGraphic->Release();
  460.     }
  461.     return TRUE;
  462. }
  463.  
  464. BOOL CAutoRect::OnCopyGraphic(LPDISPATCH DestGraphic, LPDISPATCH SourceGraphic, VARIANT*) 
  465. {
  466.     // Return FALSE on failure.
  467.     return TRUE;
  468. }
  469.  
  470. void CAutoRect::OnPropertyChanged(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  471. {
  472. }
  473.  
  474. BOOL CAutoRect::OnPropertyChanging(LPDISPATCH AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew) 
  475. {
  476.     // OK to change all of our properties, so just return TRUE.
  477.     return TRUE;
  478. }
  479.  
  480. void CAutoRect::OnPropertyGet(LPDISPATCH AGraphic, long PropID) 
  481. {
  482.     // No special recalculating of properties needed.
  483. }
  484.  
  485. BOOL CAutoRect::Draw(LPDISPATCH AGraphic, LPDISPATCH AView, VARIANT FAR* AMatrix) 
  486. {
  487.     // We don't handle special drawing, so just return FALSE.
  488.     return FALSE;
  489. }
  490.  
  491. BOOL GetVertexXYZ(IGraphic* pIGraphic, const long lVertex, double& x, double& y, double& z)
  492. {
  493.     IVertex* pIVertex = NULL;
  494.     Vertices* pVerts = NULL;
  495.     BOOL bSuccess = FALSE;
  496.     if (SUCCEEDED(pIGraphic->get_Vertices(&pVerts)))
  497.     {
  498.         COleVariant varIndex = lVertex;
  499.         if (SUCCEEDED(pVerts->get_Item(&varIndex, &pIVertex)))
  500.         {
  501.             if (SUCCEEDED(pIVertex->get_X(&x)) &&
  502.                 SUCCEEDED(pIVertex->get_Y(&y)) &&
  503.                 SUCCEEDED(pIVertex->get_Z(&z)))
  504.                 bSuccess = TRUE;
  505.             pIVertex->Release();
  506.         }
  507.         pVerts->Release();
  508.     }
  509.     return bSuccess;
  510. }
  511.  
  512. void AddLineChild(Graphics* pGraphics, double x0, double y0, double x1, double y1)
  513. {
  514.     IGraphic* pChild;
  515.     if (SUCCEEDED(pGraphics->Add(
  516.         &missing /*GraphicType*/,
  517.         &missing /*RegenMethod*/,
  518.         &t /*Inherit*/, 
  519.         &missing /*Style*/,
  520.         &missing /*Before*/,
  521.         &missing /*After*/,                    
  522.         &pChild)))
  523.     {
  524.         pChild->put_Cosmetic(TRUE);
  525.  
  526.         COleVariant x, y;
  527.         Vertices* pVerts = NULL;
  528.         IVertex* pIVertex;
  529.         if (SUCCEEDED(pChild->get_Vertices(&pVerts)))
  530.         {
  531.             x = x0;
  532.             y = y0;
  533.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  534.                 &f /*penDown*/, 
  535.                 &t /*selectable*/,
  536.                 &t /*snappable*/,
  537.                 &t /*editable*/, 
  538.                 &t /*linkable*/,
  539.                 &f /*calculated*/,
  540.                 &missing /*before*/,
  541.                 &missing /*after*/,
  542.                 &pIVertex)))
  543.                 pIVertex->Release();
  544.             x = x1;
  545.             y = y1;
  546.             if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  547.                 &t /*penDown*/, 
  548.                 &t /*selectable*/,
  549.                 &t /*snappable*/,
  550.                 &t /*editable*/, 
  551.                 &t /*linkable*/,
  552.                 &f /*calculated*/,
  553.                 &missing /*before*/,
  554.                 &missing /*after*/,
  555.                 &pIVertex)))
  556.                 pIVertex->Release();
  557.             pVerts->Release();
  558.         }
  559.         pChild->Release();
  560.     }
  561. }
  562.  
  563. void AddArcChild(Graphics* pGraphics, double xc, double yc, double r, double start, double end)
  564. {
  565.     IGraphic* pChild;
  566.     COleVariant type((long)imsiArc);
  567.     if (SUCCEEDED(pGraphics->Add(
  568.         &type /*GraphicType*/,
  569.         &missing /*RegenMethod*/,
  570.         &t /*Inherit*/, 
  571.         &missing /*Style*/,
  572.         &missing /*Before*/,
  573.         &missing /*After*/,                    
  574.         &pChild)))
  575.     {
  576.         pChild->put_Cosmetic(TRUE);
  577.         COleVariant x(xc);
  578.         COleVariant y(yc);
  579.         COleVariant rad(r);
  580.         COleVariant sa(start);
  581.         COleVariant ea(end);
  582.  
  583.         pChild->ArcSet(&x, &y, &z, &rad, &missing, &sa, &ea, &missing);
  584.         pChild->Release();
  585.     }
  586. }
  587.  
  588. void CAutoRect::Regen(LPDISPATCH AGraphic) 
  589. {
  590.     IGraphic* pIGraphic = NULL;
  591.     if (FAILED(AGraphic->QueryInterface(IID_IGraphic, (void**)&pIGraphic)))
  592.         return;
  593.  
  594.     long lockCount = 0;
  595.     if (SUCCEEDED(pIGraphic->RegenLock(&lockCount)))
  596.     {
  597.         if (lockCount == 0)
  598.         {
  599.             Graphics* pGraphics = NULL;
  600.             IGraphic* pChild = NULL;
  601.             IVertex* pIVertex = NULL;
  602.             if (SUCCEEDED(pIGraphic->get_Graphics(&pGraphics)))
  603.             {
  604.                 COleVariant flags = (const long)GF_COSMETIC;
  605.                 pGraphics->Clear(&flags);
  606.  
  607.                 // Calculate height, width and radius of corners
  608.                     
  609.                 double px[4] = { 0.0 };
  610.                 double py[4] = { 0.0 };
  611.                 double pz[4] = { 0.0 };
  612.                 for (int i = 0; i < 4; ++i)
  613.                     GetVertexXYZ(pIGraphic, i, px[i], py[i], pz[i]);
  614.  
  615.                 BOOL bHandleMoved = !(fabs(px[2] - px[3]) < 0.000001 && 
  616.                     fabs(py[2] - py[3]) < 0.000001);
  617.  
  618.                 double w = fabs(px[1] - px[0]);
  619.                 double h = fabs(py[1] - py[0]);
  620.                 double r = (w < h) ? (w/2.0) : (h/2.0);
  621.                 
  622.                 double roundness;
  623.                 if (bHandleMoved)
  624.                 {
  625.                     if (r == 0.0)
  626.                         roundness = 0.0;
  627.                     else
  628.                     {
  629.                         roundness = fabs(px[2] - px[3]) * 100.0 / r;
  630.                         if (roundness > 100.0)
  631.                             roundness = 100.0;
  632.                     }
  633.                     SetRoundness(pIGraphic, roundness);
  634.                 }
  635.                 else
  636.                 {
  637.                     roundness = GetRoundness(pIGraphic);
  638.                 }
  639.                 r = r * roundness / 100.0;                                        
  640.                     
  641.                 // Add child graphics
  642.                 // Make sure p[0] < p[1]
  643.                 double swap;
  644.                 if (px[0] > px[1])
  645.                 {
  646.                     swap = px[0];
  647.                     px[0] = px[1];
  648.                     px[1] = swap;
  649.                 }
  650.                 if (py[0] > py[1])
  651.                 {
  652.                     swap = py[0];
  653.                     py[0] = py[1];
  654.                     py[1] = swap;
  655.                 }
  656.  
  657.                 if (r == 0.0) 
  658.                 {
  659.                     // No rounded corners
  660.                     // All children are cosmetic
  661.                     if (SUCCEEDED(pGraphics->Add(
  662.                         &missing /*GraphicType*/,
  663.                         &missing /*RegenMethod*/,
  664.                         &t /*Inherit*/, 
  665.                         &missing /*Style*/,
  666.                         &missing /*Before*/,
  667.                         &missing /*After*/,                    
  668.                         &pChild)))
  669.                     {
  670.                         pChild->put_Cosmetic(TRUE);
  671.  
  672.                         COleVariant x, y;
  673.                         Vertices* pVerts = NULL;
  674.                         IVertex* pIVertex;
  675.                         if (SUCCEEDED(pChild->get_Vertices(&pVerts)))
  676.                         {
  677.                             for (int i = 0; i < 4; ++i)
  678.                             {
  679.                                 x = px[(i == 0 || i == 1) ? 0 : 1];
  680.                                 y = py[(i == 0 || i == 3) ? 0 : 1];
  681.                                 if (SUCCEEDED(pVerts->Add(&x, &y, &z,
  682.                                     (i == 0) ? &f : &t /*penDown*/, 
  683.                                     &t /*selectable*/,
  684.                                     &t /*snappable*/,
  685.                                     &t /*editable*/, 
  686.                                     &t /*linkable*/,
  687.                                     &f /*calculated*/,
  688.                                     &missing /*before*/,
  689.                                     &missing /*after*/,
  690.                                     &pIVertex)))
  691.                                     pIVertex->Release();
  692.                             }
  693.                             if (SUCCEEDED(pVerts->AddClose(
  694.                                 &t /*penDown*/, 
  695.                                 &t /*selectable*/,
  696.                                 &t /*snappable*/,
  697.                                 &t /*editable*/, 
  698.                                 &t /*linkable*/,
  699.                                 &f /*calculated*/,
  700.                                 &pIVertex)))
  701.                                 pIVertex->Release();
  702.  
  703.                             pVerts->Release();
  704.                         }
  705.                         pChild->Release();
  706.                     }
  707.                 }
  708.                 else
  709.                     {
  710.                         // Rounded corners
  711.                         // We'll make 4 line children and 4 arc children
  712.                         AddLineChild(pGraphics, px[0] + r, py[0],     px[1] - r, py[0]);
  713.                         AddArcChild (pGraphics, px[1] - r, py[0] + r, r, 1.5 * PI, 0.0);
  714.                         AddLineChild(pGraphics, px[1],     py[0] + r, px[1],     py[1] - r);
  715.                         AddArcChild (pGraphics, px[1] - r, py[1] - r, r, 0.0, 0.5 * PI);
  716.                         AddLineChild(pGraphics, px[1] - r, py[1],     px[0] + r, py[1]);
  717.                         AddArcChild (pGraphics, px[0] + r, py[1] - r, r, 0.5 * PI, PI);
  718.                         AddLineChild(pGraphics, px[0],     py[1] - r, px[0],     py[0] + r);
  719.                         AddArcChild (pGraphics, px[0] + r, py[0] + r, r, PI, 1.5 * PI);
  720.                     }
  721.                 pGraphics->Release();
  722.             }
  723.         }
  724.         pIGraphic->RegenUnlock(&missing);
  725.     }
  726.     pIGraphic->Release();
  727. }
  728.  
  729. BOOL CAutoRect::Initialize(LPDISPATCH ThisRegenMethod) 
  730. {
  731.     // TODO: Add your dispatch handler code here
  732.     return TRUE;
  733. }
  734.  
  735. // DUAL_SUPPORT_START
  736.  
  737. // delegate standard IDispatch methods to MFC IDispatch implementation
  738. DELEGATE_DUAL_INTERFACE(CAutoRect, DualRect)
  739.  
  740. // Our method and property functions can generally just
  741. // delegate back to the methods we generated using 
  742. // ClassWizard. However, if we set up properties to 
  743. // access variables directly, we will need to write the
  744. //  code to get/put the value into the variable.
  745. STDMETHODIMP CAutoRect::XDualRect::get_Description(BSTR FAR* retval)
  746. {
  747.     if (retval == NULL)
  748.         return E_POINTER;
  749.  
  750.     METHOD_PROLOGUE(CAutoRect, DualRect)
  751.  
  752.     TRY_DUAL(IID_ISmartObjectServer)
  753.     {
  754.         *retval = pThis->GetDescription();
  755.         return S_OK;
  756.     }
  757.     CATCH_ALL_DUAL
  758. }
  759.  
  760. STDMETHODIMP CAutoRect::XDualRect::get_ClassID(BSTR FAR* retval)
  761. {
  762.     if (retval == NULL)
  763.         return E_POINTER;
  764.  
  765.     METHOD_PROLOGUE(CAutoRect, DualRect)
  766.  
  767.     TRY_DUAL(IID_ISmartObjectServer)
  768.     {
  769.         *retval = pThis->GetClassID();
  770.         return S_OK;
  771.     }
  772.     CATCH_ALL_DUAL
  773. }
  774.  
  775. STDMETHODIMP CAutoRect::XDualRect::GetPropertyInfo(VARIANT FAR* Names, VARIANT FAR* Types, VARIANT FAR* IDs, VARIANT FAR* Defaults, long FAR* retval)
  776. {
  777.     if (retval == NULL)
  778.         return E_POINTER;
  779.  
  780.     METHOD_PROLOGUE(CAutoRect, DualRect)
  781.  
  782.     TRY_DUAL(IID_ISmartObjectServer)
  783.     {
  784.         *retval = pThis->GetPropertyInfo(Names, Types, IDs, Defaults);
  785.         return S_OK;
  786.     }
  787.     CATCH_ALL_DUAL
  788. }
  789.  
  790. STDMETHODIMP CAutoRect::XDualRect::GetPageInfo(IDispatch * AGraphic, long FAR* StockPages, VARIANT FAR* Names, long FAR* retval)
  791. {
  792.     if (retval == NULL)
  793.         return E_POINTER;
  794.  
  795.     METHOD_PROLOGUE(CAutoRect, DualRect)
  796.  
  797.     TRY_DUAL(IID_ISmartObjectServer)
  798.     {
  799.         *retval = pThis->GetPageInfo(AGraphic, StockPages, Names);
  800.         return S_OK;
  801.     }
  802.     CATCH_ALL_DUAL
  803. }
  804.  
  805. STDMETHODIMP CAutoRect::XDualRect::GetWizardInfo(VARIANT FAR* Names, long FAR* retval)
  806. {
  807.     if (retval == NULL)
  808.         return E_POINTER;
  809.  
  810.     METHOD_PROLOGUE(CAutoRect, DualRect)
  811.  
  812.     TRY_DUAL(IID_ISmartObjectServer)
  813.     {
  814.         *retval = pThis->GetWizardInfo(Names);
  815.         return S_OK;
  816.     }
  817.     CATCH_ALL_DUAL
  818. }
  819.  
  820. STDMETHODIMP CAutoRect::XDualRect::GetEnumNames(long PropID, VARIANT FAR* Names, VARIANT FAR* Values, long FAR* retval)
  821. {
  822.     if (retval == NULL)
  823.         return E_POINTER;
  824.  
  825.     METHOD_PROLOGUE(CAutoRect, DualRect)
  826.  
  827.     TRY_DUAL(IID_ISmartObjectServer)
  828.     {
  829.         *retval = pThis->GetEnumNames(PropID, Names, Values);
  830.         return S_OK;
  831.     }
  832.     CATCH_ALL_DUAL
  833. }
  834.  
  835. STDMETHODIMP CAutoRect::XDualRect::PageControls(IDispatch* ThisRegenMethod, IDispatch * AGraphic, long PageNumber, VARIANT_BOOL SaveProperties, VARIANT_BOOL* retval)
  836. {
  837.     if (retval == NULL)
  838.         return E_POINTER;
  839.  
  840.     METHOD_PROLOGUE(CAutoRect, DualRect)
  841.  
  842.     TRY_DUAL(IID_ISmartObjectServer)
  843.     {
  844.         *retval = pThis->PageControls(ThisRegenMethod, AGraphic, PageNumber, SaveProperties);
  845.         return S_OK;
  846.     }
  847.     CATCH_ALL_DUAL
  848. }
  849.  
  850. STDMETHODIMP CAutoRect::XDualRect::PageDone(IDispatch * ThisRegenMethod, VARIANT FAR* PageNumber)
  851. {
  852.     METHOD_PROLOGUE(CAutoRect, DualRect)
  853.  
  854.     TRY_DUAL(IID_ISmartObjectServer)
  855.     {
  856.         pThis->PageDone(ThisRegenMethod, PageNumber);
  857.         return S_OK;
  858.     }
  859.     CATCH_ALL_DUAL
  860. }
  861.  
  862. STDMETHODIMP CAutoRect::XDualRect::PropertyPages(IDispatch* ThisRegenMethod, VARIANT FAR* PageNumber, VARIANT_BOOL* retval)
  863. {
  864.     if (retval == NULL)
  865.         return E_POINTER;
  866.  
  867.     METHOD_PROLOGUE(CAutoRect, DualRect)
  868.  
  869.     TRY_DUAL(IID_ISmartObjectServer)
  870.     {
  871.         *retval = pThis->PropertyPages(ThisRegenMethod, PageNumber);
  872.         return S_OK;
  873.     }
  874.     CATCH_ALL_DUAL
  875. }
  876.  
  877. STDMETHODIMP CAutoRect::XDualRect::Wizard(IDispatch* ThisRegenMethod, VARIANT FAR* WizardNumber, VARIANT_BOOL* retval)
  878. {
  879.     if (retval == NULL)
  880.         return E_POINTER;
  881.  
  882.     METHOD_PROLOGUE(CAutoRect, DualRect)
  883.  
  884.     TRY_DUAL(IID_ISmartObjectServer)
  885.     {
  886.         *retval = pThis->Wizard(ThisRegenMethod, WizardNumber);
  887.         return S_OK;
  888.     }
  889.     CATCH_ALL_DUAL
  890. }
  891.  
  892. STDMETHODIMP CAutoRect::XDualRect::OnGeometryChanged(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew)
  893. {
  894.     METHOD_PROLOGUE(CAutoRect, DualRect)
  895.  
  896.     TRY_DUAL(IID_ISmartObjectServer)
  897.     {
  898.         pThis->OnGeometryChanged(AGraphic, GeomID, ParamOld, ParamNew);
  899.         return S_OK;
  900.     }
  901.     CATCH_ALL_DUAL
  902. }
  903.  
  904. STDMETHODIMP CAutoRect::XDualRect::OnGeometryChanging(IDispatch * AGraphic, long GeomID, VARIANT FAR* ParamOld, VARIANT FAR* ParamNew, VARIANT_BOOL* retval)
  905. {
  906.     if (retval == NULL)
  907.         return E_POINTER;
  908.  
  909.     METHOD_PROLOGUE(CAutoRect, DualRect)
  910.  
  911.     TRY_DUAL(IID_ISmartObjectServer)
  912.     {
  913.         *retval = pThis->OnGeometryChanging(AGraphic, GeomID, ParamOld, ParamNew);
  914.         return S_OK;
  915.     }
  916.     CATCH_ALL_DUAL
  917. }
  918.  
  919. STDMETHODIMP CAutoRect::XDualRect::OnNewGraphic(IDispatch * AGraphic, VARIANT_BOOL Copy, VARIANT_BOOL* retval)
  920. {
  921.     if (retval == NULL)
  922.         return E_POINTER;
  923.  
  924.     METHOD_PROLOGUE(CAutoRect, DualRect)
  925.  
  926.     TRY_DUAL(IID_ISmartObjectServer)
  927.     {
  928.         *retval = pThis->OnNewGraphic(AGraphic, Copy);
  929.         return S_OK;
  930.     }
  931.     CATCH_ALL_DUAL
  932. }
  933.  
  934. STDMETHODIMP CAutoRect::XDualRect::OnCopyGraphic(IDispatch* CopyGraphic, IDispatch* SourceGraphic, VARIANT* Matrix, VARIANT_BOOL* retval)
  935. {
  936.     if (retval == NULL)
  937.         return E_POINTER;
  938.  
  939.     METHOD_PROLOGUE(CAutoRect, DualRect)
  940.  
  941.     TRY_DUAL(IID_ISmartObjectServer)
  942.     {
  943.         *retval = pThis->OnCopyGraphic(CopyGraphic, SourceGraphic, Matrix);
  944.         return S_OK;
  945.     }
  946.     CATCH_ALL_DUAL
  947. }
  948.  
  949. STDMETHODIMP CAutoRect::XDualRect::OnPropertyChanged(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew)
  950. {
  951.     METHOD_PROLOGUE(CAutoRect, DualRect)
  952.  
  953.     TRY_DUAL(IID_ISmartObjectServer)
  954.     {
  955.         pThis->OnPropertyChanged(AGraphic, PropID, ValueOld, ValueNew);
  956.         return S_OK;
  957.     }
  958.     CATCH_ALL_DUAL
  959. }
  960.  
  961. STDMETHODIMP CAutoRect::XDualRect::OnPropertyChanging(IDispatch * AGraphic, long PropID, VARIANT FAR* ValueOld, VARIANT FAR* ValueNew, VARIANT_BOOL* retval)
  962. {
  963.     if (retval == NULL)
  964.         return E_POINTER;
  965.  
  966.     METHOD_PROLOGUE(CAutoRect, DualRect)
  967.  
  968.     TRY_DUAL(IID_ISmartObjectServer)
  969.     {
  970.         *retval = pThis->OnPropertyChanging(AGraphic, PropID, ValueOld, ValueNew);
  971.         return S_OK;
  972.     }
  973.     CATCH_ALL_DUAL
  974. }
  975.  
  976. STDMETHODIMP CAutoRect::XDualRect::OnPropertyGet(IDispatch * AGraphic, long PropID)
  977. {
  978.     METHOD_PROLOGUE(CAutoRect, DualRect)
  979.  
  980.     TRY_DUAL(IID_ISmartObjectServer)
  981.     {
  982.         pThis->OnPropertyGet(AGraphic, PropID);
  983.         return S_OK;
  984.     }
  985.     CATCH_ALL_DUAL
  986. }
  987.  
  988. STDMETHODIMP CAutoRect::XDualRect::Draw(IDispatch * AGraphic, IDispatch * AView, VARIANT FAR* AMatrix, VARIANT_BOOL* retval)
  989. {
  990.     if (retval == NULL)
  991.         return E_POINTER;
  992.  
  993.     METHOD_PROLOGUE(CAutoRect, DualRect)
  994.  
  995.     TRY_DUAL(IID_ISmartObjectServer)
  996.     {
  997.         *retval = pThis->Draw(AGraphic, AView, AMatrix);
  998.         return S_OK;
  999.     }
  1000.     CATCH_ALL_DUAL
  1001. }
  1002.  
  1003. STDMETHODIMP CAutoRect::XDualRect::Regen(IDispatch* AGraphic)
  1004. {
  1005.     METHOD_PROLOGUE(CAutoRect, DualRect)
  1006.  
  1007.     TRY_DUAL(IID_ISmartObjectServer)
  1008.     {
  1009.         pThis->Regen(AGraphic);
  1010.         return S_OK;
  1011.     }
  1012.     CATCH_ALL_DUAL
  1013. }
  1014.  
  1015. STDMETHODIMP CAutoRect::XDualRect::Initialize(IDispatch* ThisRegenMethod, VARIANT_BOOL* retval)
  1016. {
  1017.     if (retval == NULL)
  1018.         return E_POINTER;
  1019.  
  1020.     METHOD_PROLOGUE(CAutoRect, DualRect)
  1021.  
  1022.     TRY_DUAL(IID_ISmartObjectServer)
  1023.     {
  1024.         *retval = pThis->Initialize(ThisRegenMethod);
  1025.         return S_OK;
  1026.     }
  1027.     CATCH_ALL_DUAL
  1028. }
  1029.  
  1030.  
  1031. // Implement ISupportErrorInfo to indicate we support the 
  1032. // OLE Automation error handler.
  1033. IMPLEMENT_DUAL_ERRORINFO(CAutoRect, IID_ISmartObjectServer)
  1034.  
  1035. // DUAL_SUPPORT_END
  1036.